package br.academia.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import javax.faces.model.SelectItem;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import br.academia.arq.dao.MovimentacaoDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Movimentacao;
import br.academia.negocio.AbstractProcessador;
import br.academia.negocio.MovimentacaoProcessador;
import br.academia.util.Formatador;
import br.academia.util.Validador;

@SuppressWarnings("serial")
@Component("movimentacao")
@Scope("session")
public class MovimentacaoController extends AbstractController{
	/** JSPs chamadas pelo Controller */
	public static final String CADASTRAR_JSP = "/admin/movimentacao/cadastrar_movimentacao.jsf";
	public static final String ALTERAR_JSP = "/admin/movimentacao/alterar_movimentacao.jsf";
	public static final String LISTAR_JSP = "/admin/movimentacao/listar_movimentacao.jsf";
	public static final String MENU_JSP = "/admin/movimentacao/menu_movimentacao.jsf";
	
	/** Objeto usado nos fluxos do Controller */
	private Movimentacao movimentacao;
	
	/** Atributos usados nas listagens do Controller */
	private String descricao;
	private Boolean entrada;
	private String dataInicio;
	private String dataFim;
	private String valor;
	private Date formatedDataInicio;
	private Date formatedDataFim;
	private String dataFaturamento;
	
	/** Lista populada pelos fluxos */
	private Collection<Movimentacao> listaMovimentacoes;
	
	/** Combo de Movimentacoes */
	private Collection<SelectItem> comboMovimentacoes;
	
	public Collection<SelectItem> getComboMovimentacoes(){
		if(Validador.isEmpty(comboMovimentacoes)){
			MovimentacaoDAO dao = null;
			try {
				dao = getDAO(MovimentacaoDAO.class);
				
				comboMovimentacoes = toSelectItems(dao.findAll(Movimentacao.class), "id", "descricao");
			} catch (DAOException e) {
				addMensagem("Ocorreu um erro na geração da lista de Movimentacoes. Por favor, contate a administração do sistema.");
				postarMensagens();
				e.printStackTrace();
			}finally{
				close(dao);
			}
		}
		
		return comboMovimentacoes;
	}

	/**
	 * Construtor público
	 */
	public MovimentacaoController(){
		reset();
	}
	
	/**
	 * Método usado para reiniciar os atributos do Controller
	 */
	public void reset(){
		movimentacao = new Movimentacao();
		listaMovimentacoes = new ArrayList<Movimentacao>();
		dataInicio = "";
		dataFim = "";
		dataFaturamento = "";
		formatedDataInicio = null;
		formatedDataFim = null;
		entrada = null;
		descricao = "";
		valor = "";
	}
	
	/**
	 * Método utilizado para entrar no menu de Estado
	 * @return
	 */
	public String entrarMenu(){
		reset();
		
		return forward(MENU_JSP);
	}
	
	/**
	 * Método utilizado para entrar na listagem de Estado
	 * @return
	 */
	public String entrarListagem(){
		reset();
		
		return listar();
	}
	
	/**
	 * Método que popula a lista de Estados e redireciona para a listagem
	 * @return
	 */
	public String listar(){
		MovimentacaoDAO dao = null;
		
		try {
			dao = getDAO(MovimentacaoDAO.class);
			
			if(!Validador.isEmpty(dataInicio) || !Validador.isEmpty(dataFim)){
				setValores();
				
				listaMovimentacoes = dao.findMovimentacaoEntreDatas(movimentacao, formatedDataInicio, formatedDataFim);
			}else if(Validador.isEmpty(descricao) && Validador.isEmpty(dataFaturamento) && Validador.isEmpty(entrada)){
				listaMovimentacoes = dao.findAll(Movimentacao.class);
			}else{
				setValores();
				
				listaMovimentacoes = dao.findMovimentacaoLike(movimentacao);
			}
		} catch (DAOException e) {
			addMensagem("Ocorreu um erro na listagem de Movimentacoes. Por favor, contate a administração do sistema.");
			e.printStackTrace();
			return reload();
		}finally{
			if(dao != null){
				dao.close();
			}
		}
		
		if(hasMensagens()){
			return reload();
		}
		
		if(listaMovimentacoes.isEmpty()){
			addMensagem("Não foi encontrada nenhuma Movimentação para a busca realizada.");
		}
		
		return forward(LISTAR_JSP);
	}
	
	/**
	 * Método utilizado para entrar na página de alteração de Estados
	 * @return
	 */
	public String entrarAlteracao(){
		reset();
		MovimentacaoDAO dao = null;
		
		Integer id = Integer.valueOf(getParameter("id"));
		
		if(id == null || id <= 0){
			addMensagem("Ocorreu um erro na alteração do Movimentacoes selecionado. Por favor, contate a administração do sistema.");
			return reload();
		}
		
		try {
			dao = getDAO(MovimentacaoDAO.class);
			
			movimentacao = dao.findByPrimaryKey(id, Movimentacao.class);
			
			descricao = movimentacao.getDescricao();
			setEntrada(movimentacao.getEntrada() ? "1" : "2");
			valor = movimentacao.getValor().toString();
			dataFaturamento = movimentacao.getDataFaturamentoFormatada();
		} catch (DAOException e) {
			e.printStackTrace();
		}finally{
			close(dao);
		}
		return forward(ALTERAR_JSP);
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a atualização do Estado na base de dados.
	 * @return
	 */
	public String alterar(){
		addMensagem(Validador.validaPreenchimento("Descricao", descricao));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		MovimentacaoProcessador processador = new MovimentacaoProcessador();
		
		try {
			processador.execute(AbstractProcessador.ALTERAR, movimentacao);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
			return reload();
		}
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado para entrar na página de cadastro de Ideais
	 * @return
	 */
	public String entrarCadastro(){
		reset();
		
		return forward(CADASTRAR_JSP);
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a inserção do Estado na base de dados.
	 * @return
	 */
	public String cadastrar(){
		addMensagem(Validador.validaPreenchimento("Descricao", descricao));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		MovimentacaoProcessador processador = new MovimentacaoProcessador();
		
		try {
			processador.execute(AbstractProcessador.CADASTRAR, movimentacao);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado na página de listagem de Estados, para remover
	 * um Estado selecionado.
	 * @return
	 */
	public String remover(){
		Integer id = Integer.valueOf(getParameter("id"));
		
		if(id == null || id <= 0){
			addMensagem("Ocorreu um erro na remoção do item selecionado. Por favor, contate a administração do sistema.");
			return reload();
		}
		
		movimentacao.setId(id);
		
		MovimentacaoProcessador processador = new MovimentacaoProcessador();
		
		try {
			processador.execute(AbstractProcessador.REMOVER, movimentacao);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado para cancelar a operação em curso
	 * @return
	 */
	public String cancelar(){
		return entrarMenu();
	}
	
	public Movimentacao getMovimentacao() {
		return movimentacao;
	}

	public void setMovimentacao(Movimentacao movimentacao) {
		this.movimentacao = movimentacao;
	}

	private void setValores(){
		movimentacao.setDescricao(descricao.trim());
		movimentacao.setEntrada(entrada);
		
		if(!Validador.isEmpty(valor)){
			if(valor.contains(",")){
				movimentacao.setValor(Float.parseFloat(valor.replaceAll("\\.", "").replaceAll(",", ".")));
			}else{
				movimentacao.setValor(Float.parseFloat(valor));
			}
		}
		
		movimentacao.setDataFaturamento(Formatador.getInstance().parseDate(dataFaturamento));
		setFormatedDataInicio(Formatador.getInstance().parseDate(dataInicio));
		setFormatedDataFim(Formatador.getInstance().parseDate(dataFim));
	}

	public Collection<Movimentacao> getListaMovimentacoes() {
		return listaMovimentacoes;
	}

	public void setListaMovimentacoes(Collection<Movimentacao> listaMovimentacoes) {
		this.listaMovimentacoes = listaMovimentacoes;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public String getDescricao() {
		return descricao;
	}
	
	public String getEntrada() {
		if(Validador.isEmpty(entrada)){
			return "0";
		}else if(entrada){
			return "1";
		}else{
			return "2";
		}
	}

	public void setEntrada(String entrada) {
		if(entrada.toString().equals("0")){
			this.entrada = null;
		}else{
			this.entrada = (entrada.toString().equals("1"));
		}
	}

	public String getDataInicio() {
		return dataInicio;
	}

	public void setDataInicio(String dataInicio) {
		this.dataInicio = dataInicio;
	}

	public String getDataFim() {
		return dataFim;
	}

	public void setDataFim(String dataFim) {
		this.dataFim = dataFim;
	}

	public String getDataFaturamento() {
		return dataFaturamento;
	}

	public void setDataFaturamento(String dataFaturamento) {
		this.dataFaturamento = dataFaturamento;
	}

	public Date getFormatedDataInicio() {
		return formatedDataInicio;
	}

	public void setFormatedDataInicio(Date formatedDataInicio) {
		this.formatedDataInicio = formatedDataInicio;
	}

	public Date getFormatedDataFim() {
		return formatedDataFim;
	}

	public void setFormatedDataFim(Date formatedDataFim) {
		this.formatedDataFim = formatedDataFim;
	}

	public String getValor() {
		return valor;
	}

	public void setValor(String valor) {
		this.valor = valor;
	}

}
